<template>
  <div class="chat-edit-area" @click="showEmotionPanel = false">
    <!-- 文件上传进度条 -->
    <div
      :class="[
        'chat-file-progress',
        {
          'chat-file-sending': uploadStatus === 1,
          'chat-file-send-success': uploadStatus === 2,
          'chat-file-error': uploadStatus === -1
        }
      ]"
      :style="{ width: `${percent}%` }"></div>
    <!--工具栏-->
    <div class="flex-row chat-edit-toolbar">
      <!--富文本编辑器内置菜单-->
      <!--      <Toolbar class="chat-editor-toolbar" :editor="editor" :default-config="toolbarConfig"/>-->
      <!--用户自定义菜单-->
      <div class="flex-row flex-item">
        <!--左侧菜单-->
        <div class="flex-row flex-item">
          <div class="chat-menu" title="表情" @click.stop="showEmotion">
            <i class="fy-icon-happy toolbar-icon"></i>
          </div>
          <div class="chat-menu" title="发送图片">
            <ElUpload
              ref="uploadImage"
              class="upload-demo"
              :accept="['.png', '.jpg', '.jpeg', '.gif', '.bmp'].join(',')"
              :show-file-list="false"
              :http-request="ctx => uploadFile(ctx, 'image')"
              :action="action"
              :before-upload="beforeUpload"
              :disabled="readonly"
              :data="bizInfo"
              auto-upload>
              <template #trigger>
                <i class="el-icon-picture toolbar-icon"></i>
              </template>
            </ElUpload>
          </div>
          <div class="chat-menu" title="发送文件">
            <ElUpload
              ref="uploadFile"
              class="upload-demo"
              :show-file-list="false"
              :http-request="ctx => uploadFile(ctx, 'file')"
              :action="action"
              :before-upload="beforeUpload"
              :disabled="readonly"
              :data="bizInfo"
              auto-upload>
              <template #trigger>
                <i class="el-icon-upload toolbar-icon"></i>
              </template>
            </ElUpload>
          </div>
        </div>
        <!--右侧菜单-->
        <div>
          <div class="chat-menu" title="聊天记录">
            <i class="el-icon-time toolbar-icon" @click="showHistory = true"></i>
          </div>
        </div>
      </div>
    </div>
    <!--编辑区-->
    <CustomScrollbar v-show="!readonly" class="flex-item">
      <Editor
        ref="editor"
        v-model="text"
        mode="simple"
        class="absolute"
        :default-config="editorConfig"
        @keyup.native="sendMsg"
        @customPaste="customPaste"
        @onCreated="onEditorCreated"
        @onChange="onChange" />
    </CustomScrollbar>
    <EmptyView v-show="readonly" :empty-tips="disabledTips" font-size="14px" />

    <!--底部-->
    <div class="footer">
      <ElButton v-if="closeable" size="mini" title="关闭(Esc)" @click="close">关闭</ElButton>
      <ElButton
        :disabled="contentEmpty || sending"
        :title="contentEmpty ? '' : 'Ctrl+Enter'"
        :loading="sending"
        size="mini"
        type="primary"
        @click="sendToServer()">
        发 送
      </ElButton>
    </div>
    <!--消息记录对话框-->
    <ChatHistoryDialog :key="session.id" :session="session" :visible.sync="showHistory" />
    <!--表情面板-->
    <Emotion
      v-show="showEmotionPanel"
      :style="{ left }"
      style="position: absolute; top: -262px; z-index: 2"
      @mouseleave="showEmotionPanel = false"
      @item-click="insertEmotion" />
  </div>
</template>

<script>
  import { uploadFile } from '@/api/file'
  import ChatHistoryDialog from './ChatHistoryDialog'
  import blockquote from './editor-plugins/blockquote'
  import { Boot } from '@wangeditor/editor'
  import { Editor } from '@wangeditor/editor-for-vue'
  import '@wangeditor/editor/dist/css/style.css'
  import { delay } from '@web-utils/core'
  import Emotion from '@/views/playground/widgets/Emotion'
  import { sendMessage } from '@/components/im/api/message'
  import { services } from '@/config'

  Boot.registerModule(blockquote)

  function isEmpty(children) {
    if (!children) {
      return true
    }
    for (let i = 0; i < children.length; i++) {
      const child = children[i]
      const type = child.type
      if (type === 'image') {
        return false
      } else if (type === 'paragraph') {
        return isEmpty(child.children)
      } else if (child.text) {
        return false
      }
    }
    return true
  }

  const delayTime = 3000
  // https://www.wangeditor.com/
  export default {
    name: 'ChatRichTextEditAreaNew',
    components: {
      Emotion,
      ChatHistoryDialog,
      Editor
    },
    props: {
      session: {
        type: Object,
        default: () => {}
      },
      closeable: {
        type: Boolean,
        default: false
      },
      disabled: Boolean,
      disabledTips: String
    },
    data() {
      return {
        editor: null,
        showEmotionPanel: false,
        showHistory: false,
        sending: false,
        percent: 0,
        uploadStatus: 0,
        left: '0px',
        text: '',
        contentEmpty: true,
        editorConfig: {
          maxLength: 1000,
          placeholder: '按 Ctrl + Enter 发送',
          scroll: false
        }
        // toolbarConfig: {
        //   modalAppendToBody: true,
        //   toolbarKeys: []
        // }
      }
    },
    computed: {
      action() {
        return `${services.commonService}file/upload`
      },
      readonly() {
        return this.disabled || !this.session || !this.session.id
      },
      bizInfo() {
        return {
          bizId: this.session.thread?.id,
          bizName: 'IM'
        }
      }
    },
    watch: {
      readonly: {
        immediate: true,
        async handler() {
          await this.$nextTick()
          if (this.readonly) {
            this.editor?.disable()
          } else {
            this.editor?.enable()
          }
        }
      }
    },
    beforeDestroy() {
      this.editor.destroy()
    },
    methods: {
      customPaste(editor, event, insert) {
        // event 是 ClipboardEvent 类型，可以拿到粘贴的数据
        // 可参考 https://developer.mozilla.org/zh-CN/docs/Web/API/ClipboardEvent

        const html = event.clipboardData.getData('text/html') // 获取粘贴的 html
        if (html) {
          // const text = event.clipboardData.getData('text/plain') // 获取粘贴的纯文本
          // const rtf = event.clipboardData.getData('text/rtf') // 获取 rtf 数据（如从 word wsp 复制粘贴）
          // editor.dangerouslyInsertHtml(html)
          // event.preventDefault()
          // insert(false)
          // return
        }
        insert(true)
      },
      onEditorCreated(editor) {
        this.editor = Object.seal(editor)
      },
      onChange() {
        this.contentEmpty = isEmpty(this.editor.children)
      },
      async uploadFile(obj, type) {
        try {
          const res = await uploadFile(obj.action, obj.file, {
            headers: obj.headers,
            onprogress: this.onUploadProgress,
            data: obj.data
          })
          if (type === 'file') {
            await this.onFileUploadSuccess(res.data)
          }
          if (type === 'image') {
            await this.onImageUploadSuccess(res.data)
          }
        } catch (e) {
          await this.onUploadError()
        }
      },
      close() {
        this.$emit('close')
      },
      insertEmotion(position) {
        this.editor.restoreSelection()
        this.editor.dangerouslyInsertHtml(
          `<img src="./static/img/emotion/${position}.gif" class="im-chat-emotion" alt="[表情]" data-emotion="${position}">`
        )
      },
      showEmotion(event) {
        if (this.readonly) {
          return
        }
        if (!this.showEmotionPanel) {
          const target = event.target
          this.left = `${target.clientLeft - 3}px`
          this.showEmotionPanel = true
        } else {
          this.showEmotionPanel = false
        }
      },
      sendMsg(e) {
        if (!this.contentEmpty && e.ctrlKey && e.keyCode === 13) {
          this.sendToServer()
        }
      },
      async sendToServer(type = 'text', mediaId, filename) {
        try {
          this.sending = true
          let text = filename
          if (type === 'text') {
            text = this.text
            const temp = this.text.replace(/&nbsp;/g, '').trim()
            if (!temp) {
              this.editor.clear()
              this.text = ''
              this.sending = false
              return
            }
          }

          const reply = this.editor.children.find(value => value.type === 'reply')

          const res = await sendMessage({
            threadId: this.session.thread.id,
            mediaId,
            content: text,
            replyId: type === 'text' ? reply?.id : null,
            type
          })

          if (type === 'text') {
            this.editor.clear()
            this.text = ''
          }
          this.$emit('send-success', res.data.data)
        } catch (e) {
          this.$notify.error({
            title: '温馨提示',
            message: '发送失败！',
            position: 'bottom-right',
            duration: 2000
          })
        }
        this.sending = false
      },
      beforeUpload() {
        this.uploadStatus = 1
        return true
      },
      onUploadProgress(event) {
        this.uploadStatus = 1
        this.percent = event.percent
      },
      async onImageUploadSuccess(response) {
        this.uploadStatus = 2
        const { data } = response
        await this.sendToServer('image', data.id, data.filename)
        this.$refs.uploadImage.clearFiles()
        await delay(delayTime)
        this.uploadStatus = 0
      },
      async onFileUploadSuccess(response) {
        this.uploadStatus = 2
        const { data } = response
        await this.sendToServer('file', data.id, data.filename)
        this.$refs.uploadFile.clearFiles()
        await delay(delayTime)
        this.uploadStatus = 0
      },
      async onUploadError() {
        this.uploadStatus = -1
        this.$message.error('文件发送失败，请重试或联系管理员！')
        await delay(delayTime)
        this.$refs.uploadImage.clearFiles()
        this.$refs.uploadFile.clearFiles()
        this.uploadStatus = 0
      }
    }
  }
</script>

<style lang="scss">
  .chat-edit-area {
    @include flex-not-shrink;
    position: relative;
    z-index: 0;
    display: flex;
    flex-direction: column;
    height: 100%;
    background: #fff;
    border-bottom: solid 1px #e0e0e0;
    border-bottom: none;
    border-radius: 0 0 4px;

    // .w-e-hover-bar.w-e-bar-show {
    //   display: none;
    // }
    .w-e-max-length-info {
      display: none;
    }

    /* .chat-editor-toolbar {

      > .w-e-bar {
        background-color: transparent;

        > .w-e-bar-item {
          height: unset;

          button {
            height: unset;

            &:hover {
              background-color: transparent;
            }
          }
        }
      }
    } */

    .chat-file-progress {
      position: absolute;
      top: 0;
      width: 0;
      height: 2px;
      background-color: #f7f7f7;
    }

    .chat-file-sending {
      background-color: var(--color-primary);
    }

    .chat-file-send-success {
      background-color: #80d954;
    }

    .chat-file-error {
      background-color: #f00;
    }

    .footer {
      flex-basis: 40px;
      flex-shrink: 0;
      height: 40px;
      min-height: 40px;
      padding: 6px;
      text-align: right;
    }

    .textarea {
      position: absolute;
      top: 0;
      right: 0;
      bottom: 0;
      left: 0;
      padding: 10px;
      font-family: 'Micrsofot Yahei', sans-serif;
    }

    .chat-editor-wrapper {
      position: relative;
      flex: 1 1 auto;
      height: 100%;
      overflow: auto;

      .os-content {
        min-height: 100%;
      }

      .chat-editor {
        position: absolute;
        top: 0;
        bottom: 0;
        width: 100%;
        height: 100%;
        cursor: text;

        &::after {
          position: absolute;
          top: 10px;
          left: 11px;
          color: #a9a9a9;
          content: attr(placeholder);
          pointer-events: none;
        }
      }
    }

    .chat-edit-toolbar {
      align-items: center;
      background-color: #eee;

      .chat-menu {
        position: relative;
        padding: 5px 6px;
        text-align: center;
        cursor: pointer;
      }

      .toolbar-icon {
        color: #999;
        font-size: 1.2em;
        cursor: pointer;

        &:hover {
          color: #333;
        }
      }
    }
  }
</style>
